/**********************************************************************************************************
** 驱动文件：	dianli-EM100.c
** 驱动类型：	dianli
** 设备名称：	电力监测
** 设备型号：	EM100
** 设备品牌：	融智云
** 设备协议：	Modbus-RTU
** 驱动描述：	EM100单相多功能电力电量仪，具备实时电压、电流、频率、电能、有功、无功等电量采集功能。
** 生成日期：	2020-05-01 11:30:30
**********************************************************************************************************/
#include "Includes.h"


/**********************************************************************************************************
* 定义设备数据点变量结构
**********************************************************************************************************/
typedef struct{
	Var Voltage;								//电压
	Var Current;								//电流
	Var ActivePower;							//有功功率
	Var ReactivePower;							//无功功率
	Var ApparentPower;							//视在功率
	Var PowerFactor;							//功率因数
	Var Frequency;								//电压频率
	Var TotalActiveEnergy;						//总有功电能
	Var TotalReactiveEnergy;					//总无功电能
}Data_Struct;									//定义变量结构


/**********************************************************************************************************
* 设备数据点变量属性声明
**********************************************************************************************************/
const static Var_Property_Def var_attr[] = {
	{
		FLOAT,
		0,
		READONLY,
		"Voltage",
		"电压",
		"V",
		"电压",
		0,
		0,
		"电压过高",
		"电压过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"Current",
		"电流",
		"A",
		"电流",
		0,
		0,
		"电流过高",
		"电流过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"ActivePower",
		"有功功率",
		"W",
		"有功功率",
		0,
		0,
		"有功功率过高",
		"有功功率过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"ReactivePower",
		"无功功率",
		"Var",
		"无功功率",
		0,
		0,
		"无功功率过高",
		"无功功率过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"ApparentPower",
		"视在功率",
		"VA",
		"视在功率",
		0,
		0,
		"视在功率过高",
		"视在功率过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"PowerFactor",
		"功率因数",
		"",
		"功率因数",
		0,
		0,
		"功率因数过高",
		"功率因数过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"Frequency",
		"电压频率",
		"Hz",
		"电压频率",
		0,
		0,
		"电压频率过高",
		"电压频率过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"TotalActiveEnergy",
		"总有功电能",
		"KW•h",
		"总有功电能",
		0,
		0,
		"总有功电能过高",
		"总有功电能过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"TotalReactiveEnergy",
		"总无功电能",
		"KVar•h",
		"总无功电能",
		0,
		0,
		"总无功电能过高",
		"总无功电能过低",
		0,
		0
	}
};


/**********************************************************************************************************
* 函数名称： static void cmd_fun(short index, int addr, void *data, char *cmd, short *len)
* 函数说明： 生成获取传感器数据指令
* 输入参数： 指令索引，传感器地址，变量结构体指针,以及指令缓存区指针,指令长度
* 返回参数： 无
**********************************************************************************************************/
static void cmd_fun(short index, int addr, void *data, char *cmd, short *len)
{
	switch(index)
	{
		case 0:
			cmd[0] = addr;
			cmd[1] = 0x04;
			cmd[2] = 0x00;								
			cmd[3] = 0x00;
			cmd[4] = 0x00;	
			cmd[5] = 0x1F;
			*len = CRC16_Padding(cmd, 6);
			break;
		case 1:
			cmd[0] = addr;
			cmd[1] = 0x04;
			cmd[2] = 0x00;								
			cmd[3] = 0x3B;
			cmd[4] = 0x00;	
			cmd[5] = 0x02;
			*len = CRC16_Padding(cmd, 6);
			break;
		default:
			break;
	}
}


/**********************************************************************************************************
* 函数名称： static int parse_fun(short index, int addr, void *data, char *buf, short len)
* 函数说明： 解析传感器响应的数据，并写入数据库
* 输入参数： 解析索引,传感器地址，变量结构体指针，以及响应数据缓存取指针，响应数据长度
* 返回参数： 返回解析结果，返回0成功，返回1失败
**********************************************************************************************************/
static int parse_fun(short index, int addr, void *data, char *buf, short len)
{
	union{
		short 			dat16;
      	unsigned char  	dat8[2];
    }DAT16_8;						   //数据类型转换	
    union 		   					 
    {
		unsigned int	dat32;
		unsigned char   dat8[4];
    }DAT32_8;							//数据类型转换		
	Data_Struct 	*d = (Data_Struct*)data;

	if(buf!=NULL && buf[0]==addr && len>0 )
	{	
		if(CRC16_Check(buf,len))
		{
			switch(index)
			{
				case 0:
					DAT16_8.dat8[1] = buf[3];
					DAT16_8.dat8[0] = buf[4];
					d->Voltage.value.fnum = DAT16_8.dat16*0.1;

					DAT16_8.dat8[1] = buf[9];
					DAT16_8.dat8[0] = buf[10];
					d->Current.value.fnum = DAT16_8.dat16*0.01;
							
					DAT16_8.dat8[1] = buf[17];
					DAT16_8.dat8[0] = buf[18];
					d->ActivePower.value.fnum = DAT16_8.dat16*1.0;
		
					DAT16_8.dat8[1] = buf[25];
					DAT16_8.dat8[0] = buf[26];
					d->ReactivePower.value.fnum = DAT16_8.dat16*1.0;
	
					DAT16_8.dat8[1] = buf[33];
					DAT16_8.dat8[0] = buf[34];
					d->ApparentPower.value.fnum = DAT16_8.dat16*1.0;
			
					DAT16_8.dat8[1] = buf[41];
					DAT16_8.dat8[0] = buf[42];
					d->PowerFactor.value.fnum = DAT16_8.dat16*0.001;	
					
					DAT16_8.dat8[1] = buf[55];
					DAT16_8.dat8[0] = buf[56];
					d->Frequency.value.fnum = DAT16_8.dat16*0.01;

					DAT32_8.dat8[3] = buf[61];
					DAT32_8.dat8[2] = buf[62];
					DAT32_8.dat8[1] = buf[63];
					DAT32_8.dat8[0] = buf[64];
					d->TotalActiveEnergy.value.fnum = DAT32_8.dat32*0.01;
					break;					
				case 1:	
					DAT32_8.dat8[3] = buf[3];
					DAT32_8.dat8[2] = buf[4];
					DAT32_8.dat8[1] = buf[5];
					DAT32_8.dat8[0] = buf[6];
					d->TotalReactiveEnergy.value.fnum = DAT32_8.dat32*0.01;
					break;
				default:
					break;
			}
			return 0;
		}
	}
	return 1;
}


/**********************************************************************************************************
* 函数名称： void dianli_EM100_Registration(void)
* 函数说明： 电力监测驱动注册
* 输入参数： 无
* 返回参数： 无
**********************************************************************************************************/
void dianli_EM100_Registration(void)
{
	DeviceDriverRegistration(
		"dianli",												//设备类型
		"电力监测",												//设备名称（导航栏默认显示名称）
		"融智云",												//设备品牌
		"EM100",												//设备型号
		"EM100单相多功能电力电量仪，具备实时电压、电流、频率、电能、有功、无功等电量采集功能。",//驱动描述
		var_attr,												//变量属性声明
		sizeof(Data_Struct),									//变量结构体空间大小
		cmd_fun,												//发送指令生成函数
		parse_fun,												//数据解析函数
		250														//设备响应超时时间
	);
		
#if 0 || VirtualFrameEN
	#define	CMD1	"\x01\x04\x00\x00\x00\x1F\xB1\xC2"
	#define	RSP1	"\x01\x04\x3E\x0B\x20\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\xFF\xFA\xFF\xFA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x05\x00\x00\x00\x00\x22\x55\x22\x55\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x88\x00\x00\x00\x00\x00\x00\x00\x00\xA8\xE1"
	#define	CMD2	"\x01\x04\x00\x3B\x00\x02\x00\x06"
	#define	RSP2	"\x01\x04\x04\x00\x00\x00\x00\xFB\x84"	

	VirtualFrameRegistration(CMD1, sizeof(CMD1)-1, RSP1, sizeof(RSP1)-1);
	VirtualFrameRegistration(CMD2, sizeof(CMD2)-1, RSP2, sizeof(RSP2)-1);
#endif	
}

